#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>

#include "armsdkerr.h"
#include "armsdkcmdregister.h"



INT4 adSDKCmdStrRegister(CHR *data_str)
{
    return add_cmdList(&gu1CmdList, data_str);
}

cmdStrList_t *create_cmdList_node(CMDS_ADDR data_str)
{
    INT4 i4Cnt = 0;
    cmdStrList_t *new_cmdStr = (cmdStrList_t *)malloc(sizeof(cmdStrList_t));
    if (new_cmdStr == NULL)
    {
        MEM_LLOC_ERR(NULL);
    }
    MEMSET(new_cmdStr, 0, sizeof(cmdStrList_t));

    for (i4Cnt = 0; data_str[i4Cnt] != NULL; i4Cnt ++)
    {
        STRCPY(new_cmdStr->au1CmdStrPtr[i4Cnt], data_str[i4Cnt]);
    }
    new_cmdStr->next = NULL;


    free(data_str[0]);

    return new_cmdStr;
}

INT4 adSDKCmdStrParse(CHR *cmd, CMDS_ADDR pu1CmdWords)
{
    INT4 i4Inc = 0;
    INT4 i4wCnt = 0;
    BOOL i4Sbl = FALSE;
    BOOL newLine = TRUE;
    CHR *endPtr = NULL;
    CHR leftsbl = '\0';
    INT4 samesbls = 0;

    CHR *cmdStr = (CHR *)malloc(CMD_STR_WORDS * CMD_WORD_LEN);
    if (cmdStr == NULL)
    {
        MEM_LLOC_ERR(FAILURE);
    }
    MEMSET(cmdStr, 0, CMD_STR_WORDS * CMD_WORD_LEN);

    MEMCPY(cmdStr, cmd, strlen(cmd));

    while(cmdStr[i4Inc] != '\0')
    {
        switch (cmdStr[i4Inc])
        {
            case ' ':
                if (i4Sbl != TRUE)
                {
                    newLine = TRUE;
                }
                break;
            case '{':
            case '[':
            case '(':
                if (i4Sbl == FALSE)
                {
                    i4Sbl = TRUE;
                    newLine = TRUE;
                    leftsbl = cmdStr[i4Inc];
                }
                else
                {
                    if (leftsbl == cmdStr[i4Inc])
                    {
                        samesbls ++;
                    }
                }
                break;
            case '}':
            case ']':
            case ')':
                if (i4Sbl == FALSE)
                {
                    PRINTF(" * invalid command format!\n");
                    return FAILURE;
                }
                if ((leftsbl == '{' && cmdStr[i4Inc] == '}') ||
                    (leftsbl == '[' && cmdStr[i4Inc] == ']') ||
                    (leftsbl == '(' && cmdStr[i4Inc] == ')'))
                {
                    if (samesbls !=0)
                    {
                        samesbls --;
                    }
                    else
                    {
                        i4Sbl = FALSE;
                        newLine = TRUE;
                    }
                }
                break;
            default:
                break;
        }

        if (newLine == TRUE && pu1CmdWords[i4wCnt] == NULL)
        {
            if ((cmdStr[i4Inc] == '{' || cmdStr[i4Inc] == '[' || 
                cmdStr[i4Inc] == '(') && i4Sbl == TRUE)
            {
                cmdStr = cmdStr + i4Inc;
                i4Inc = 0;
            }
            else if ((cmdStr[i4Inc] == '}' || cmdStr[i4Inc] == ']' || 
                     cmdStr[i4Inc] == ')') && i4Sbl == FALSE)
            {
                cmdStr = cmdStr + i4Inc + 1;
                i4Inc = 0;
                continue;
            }
            else if (cmdStr[i4Inc] == ' ')
            {
                endPtr = cmdStr + i4Inc;
                cmdStr = cmdStr + i4Inc + 1;
                i4Inc = 0;
                *endPtr = '\0';
                continue;
            }

            pu1CmdWords[i4wCnt] = &cmdStr[i4Inc];
            i4wCnt ++;
            newLine = FALSE;
        }
        i4Inc ++;
    }
    return SUCCESS;
}

INT4 add_cmdList(cmdStrList_t *cmdListHead, CHR *data_str)
{
    /* parse cmds strings from input */
    CMDS_ADDR au1cmdwords = {NULL};
    adSDKCmdStrParse(data_str, au1cmdwords);

    cmdStrList_t *new_cmdStr = create_cmdList_node(au1cmdwords);

    cmdStrList_t *cur_cmdStr = cmdListHead;
    while (cur_cmdStr->next != NULL)
    {
        cur_cmdStr = cur_cmdStr->next;
    }
    cur_cmdStr->next = new_cmdStr;

    return SUCCESS;
}

INT4 print_cmdList(cmdStrList_t *cmdListHead)
{
    INT4 i4Cnt;
    if (cmdListHead == NULL)
    {
        return SUCCESS;
    }

    cmdStrList_t *cur_cmdStr = cmdListHead;

    while (cur_cmdStr->next != NULL)
    {
        cur_cmdStr = cur_cmdStr->next;
        for (i4Cnt = 0; cur_cmdStr->au1CmdStrPtr[i4Cnt] != NULL; i4Cnt ++)
        {
#if DEBUG_MODE
            ARM_SDK_DEBUG("%s\n", cur_cmdStr->au1CmdStrPtr[i4Cnt]);
#else
            PRINTF("%s\n", cur_cmdStr->au1CmdStrPtr[i4Cnt]);
#endif
        }
    }

    return SUCCESS;
}

CHR *research_cmdList(cmdStrList_t *retList, CHR *input, INT4 i4Cnt)
{
    BOOL isCmd = FALSE;
    CHR *pu1CmdListRet = (CHR *)malloc(CMD_WORD_LEN);
    if (pu1CmdListRet == NULL)
    {
        MEM_LLOC_ERR(NULL);
    }
    MEMSET(pu1CmdListRet, 0, CMD_WORD_LEN);

    cmdStrList_t *cur_cmdStr = retList;

    while (cur_cmdStr->next != NULL)
    {
        cur_cmdStr = cur_cmdStr->next;
        if (strstr(cur_cmdStr->au1CmdStrPtr[i4Cnt], input))
        {
            isCmd = TRUE;
            if (cur_cmdStr->au1CmdStrPtr[i4Cnt + 1] != NULL)
            {
                SNPRINTF(pu1CmdListRet + strlen(pu1CmdListRet), 
                        CMD_WORD_LEN - strlen(pu1CmdListRet), 
                        "%s ", cur_cmdStr->au1CmdStrPtr[i4Cnt + 1]);
            }
        }
    }
    if (isCmd == FALSE)
    {
        free (pu1CmdListRet);
        pu1CmdListRet = NULL;
    }

    return pu1CmdListRet;
}

INT4 match_cmdInput(CHR **input, CHR **cmdArgs, INT4 *pi4ArgNum)
{
    INT4 i4Inc = 0;
    INT4 i4WordNum = 0;
    INT4 i4CmdNum = 0;
    CHR *pu1matchStr = NULL;
    cmdStrList_t *cur_cmdStr = &gu1CmdList;

    if (cur_cmdStr->next == NULL)
    {
        return FAILURE;
    }

    while (cur_cmdStr != NULL)
    {
        for (i4WordNum = 0; input[i4WordNum] != NULL; i4WordNum ++)
        {
            if (cur_cmdStr->au1CmdStrPtr[i4WordNum] == NULL)
            {
                COMMAND_ERR();
            }
            pu1matchStr = strstr(cur_cmdStr->au1CmdStrPtr[i4WordNum], input[i4WordNum]);

            if (pu1matchStr)
            {
                if (strchr(cur_cmdStr->au1CmdStrPtr[i4WordNum], '{') || 
                    strchr(cur_cmdStr->au1CmdStrPtr[i4WordNum], '[') ||
                    strchr(cur_cmdStr->au1CmdStrPtr[i4WordNum], '('))
                {
                    MEMCPY(cmdArgs[*pi4ArgNum], input[i4WordNum], strlen(input[i4WordNum]));
                    *pi4ArgNum = *pi4ArgNum + 1;

                    /* ADTAG: add by xueda on 2025/6/17, 
                     * comment: 判断参数是否有二级参数*/
                    if (strstr(pu1matchStr, "STR"))
                    {
                        i4WordNum += 1;
                        if (input[i4WordNum] != NULL)
                        {
                            MEMCPY(cmdArgs[*pi4ArgNum], input[i4WordNum], strlen(input[i4WordNum]));
                            *pi4ArgNum = *pi4ArgNum + 1;
                        }
                        else
                        {
                            COMMAND_ERR();
                        }
                    }
                }

                pu1matchStr = NULL;
                continue;
            }
            else
            {
                if (MEMCMP(cur_cmdStr->au1CmdStrPtr[i4WordNum], "STR", 3) == 0)
                {
                    MEMCPY(cmdArgs[*pi4ArgNum], input[i4WordNum], strlen(input[i4WordNum]));
                    *pi4ArgNum = *pi4ArgNum + 1;
                    continue;
                }
                break;
            }
        }
        if (input[i4WordNum] == NULL)
        {
            return (i4CmdNum - 1);
        }

        if (cur_cmdStr->next != NULL)
        {
            for (i4Inc = 0; i4Inc < (*pi4ArgNum); i4Inc ++)
            {
                MEMSET(cmdArgs[i4Inc], 0, CMD_WORD_LEN);
            }

            *pi4ArgNum = 0;
            i4CmdNum ++;
            cur_cmdStr = cur_cmdStr->next;
        }
        else
        {
            return FAILURE;
        }
    }
}

INT4 destroy_cmdList(cmdStrList_t cmdListHead)
{
    if (cmdListHead.next == NULL)
    {
        return SUCCESS;
    }

    cmdStrList_t *cur_cmdStr = cmdListHead.next;
    cmdStrList_t *next_cmdStr = NULL;

    while (cur_cmdStr->next != NULL)
    {
        next_cmdStr = cur_cmdStr->next;
        free(cur_cmdStr);
        cur_cmdStr = next_cmdStr;
    }

    /* 释放最后一个节点 */
    free(cur_cmdStr);

    return SUCCESS;
}

